package com.common.web.dataset.context;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.common.base.persistence.Page;
import com.common.web.dataset.description.DataSetDescription;
import com.common.web.dataset.reflect.ObjectUtils;
import com.common.web.dataset.vo.ColsVO;
import com.common.web.dataset.vo.RowsVO;

/**
 * DataSet上下文
 * @author lj
 * @date 2016年12月13日15:26:28
 */
class DataSetContext {
	
	private static final Logger LOG = LoggerFactory.getLogger(DataSetContext.class);
	
	// key:class name
	private Map<String,DataSetDescription> descriptions = new HashMap<String,DataSetDescription>();
	
	// 从descriptions中获取DataSetDescription，如果没有，则实例化一个DataSetAnnotationHandler去获取DataSetDescription，
	// 并加入到descriptions中
	/**
	 * 得到 DataSetDescription 即 DataSet描述
	 * @param clazz
	 * @return
	 * @throws ClassNotFoundException 
	 */
	public DataSetDescription getDescription(Class<?> clazz) throws ClassNotFoundException{
		String clazzName = clazz.getName();
		if(descriptions.containsKey(clazzName)){
			DataSetDescription description = descriptions.get(clazzName);
			return description;
		} else {
			DataSetAnnotationHandler handler = new DataSetAnnotationHandler(clazz);
			DataSetDescription description = handler.handle();
			
			descriptions.put(clazzName, description);
			
			return description;
		}
	}

	/**
	 * 将list集合数据转为rows数据
	 * @param list
	 * @param description
	 * @param cols
	 * @param clazz
	 * @return
	 */
	public List<RowsVO> toDataSetRowList(Page<?> page, DataSetDescription description,List<ColsVO> cols, Class<?> clazz) {
		List<?> list = page.getList();
		List<RowsVO> rows = new ArrayList<RowsVO>();
		
		for(int i=0;i<list.size();i++){
			Object object = list.get(i);
			RowsVO row = new RowsVO();
			if (description.getIdAttr()==null || description.getIdAttr().isEmpty()) {
				row.setId(String.valueOf(i));
			} else {
				Object id = ObjectUtils.getProperty(object, description.getIdAttr());
				row.setId(String.valueOf(id));
			}
			row.setCss(description.getCss());
			row.setCssClass(description.getCssClass());
			
			List<Object> data = new ArrayList<Object>();
			for (int j = 0; j < cols.size(); j++) {
				ColsVO col = cols.get(j);
				String fieldName = col.getName();
				String type = col.getType();
				Object value = ObjectUtils.getProperty(object, fieldName);
				if (value == null) {
					data.add(""); // 当数据为空时，用空串填充
					continue ;
				}
				// 对日期类型做格式转化
				if (type.equals("date")) {
					Date date = (Date)value;
					value = DateFormatUtils.format(date, col.getDateFormat());
				}
				// filedOfFiledName 如果此列数据是一个自定义的对象，此处把该对象的filedOfFiledName属性的值作为传递到前端的值
				String filedOfFiledName = col.getFieldOfFiledName();
				if("object".equals(type) && filedOfFiledName!=null && !"".equals(filedOfFiledName.trim())){
					value = ObjectUtils.getProperty(value, filedOfFiledName);
				}
				// filedOfMethodName 如果此列数据是一个自定义的对象，此处调用该对象的filedOfMethodName方法的返回值作为传递到前端的值
				String filedOfMethodName = col.getFieldOfMethodName();
				if (filedOfMethodName!=null && !"".equals(filedOfMethodName.trim())) {
					Method method = ObjectUtils.getMethod(value, filedOfMethodName);
					try {
						value = method.invoke(value, null);
					} catch (IllegalArgumentException e) {
						LOG.error(e.getMessage());
					} catch (IllegalAccessException e) {
						LOG.error(e.getMessage());
					} catch (InvocationTargetException e) {
						LOG.error(e.getMessage());
					}
				}
				// invokeMethodName 如果此列数据是一个其它类型的对象（List,Map,Set，数组等），此处调用object的invokeMethodName方法的返回值作为传递到前端的值
				String invokeMethodName = col.getInvokeMethodName();
				if (invokeMethodName!=null && !"".equals(invokeMethodName.trim())) {
					Method method = ObjectUtils.getMethod(object, invokeMethodName);
					try {
						value =  method.invoke(object, null);
					} catch (IllegalArgumentException e) {
						LOG.error(e.getMessage());
					} catch (IllegalAccessException e) {
						LOG.error(e.getMessage());
					} catch (InvocationTargetException e) {
						LOG.error(e.getMessage());
					}
				}
				data.add(value);
			}
			row.setData(data);
			rows.add(row);
		}
		return rows;
		
	}

}
